/*
    布尔类型（boolean）
    数字类型（number）
    字符串类型（string）
    数组类型（array）
    元组类型（tuple）
    枚举类型（enum）
    任意类型（any）
    null和undefined
    void类型:表示没有任何类型，一般用于定义方法的时候，方法没有返回值。
    never类型:其他类型（包括null 和 undefined）的子类型，代表从不会出现的值，这就意味着声明never的变量只能被never类型所赋值。
 */

//布尔类型（boolean） true false
var flag:boolean = true
flag = false

//数字类型（number）
var a:number = 123

a = 12.3
console.log(a)

//字符串类型（string）
var str:string = "this is ts"

//数组类型（array） ts中定义数组有两种方式
//es5 var arr = [1,"123",false]
//1、第一种定义方式
let arr1:number[] = [1,2,3,4,5]
console.log(arr1)
let arr2:string[] = ["php","js",'golang']
console.log(arr2)
//2、第二种定义方式
let arr3:Array<number> = [11,22,33,44,55]
console.log(arr3)
let arr4:Array<string> = ["aaa","bbb","ccc"]
//3、第三种方式
let arr5:any[] = ['123',123,true]
console.log(arr5)

//元组类型（tuple） 属于数组一种
let arr6:[string,number,boolean] = ["aaa",123,true]

//枚举类型（enum）
enum Flag {success =1,error = -1}
var f:Flag = Flag.error
console.log(f)
enum Color {red,blue,orange}
var c:Color = Color.blue
console.log(c)

//任意类型（any）
var num1:any = 123;
num1 = "str";
num1 = true;
console.log(num1)
//任意类型的用处
var oBox:any = document.getElementById('box');
oBox.style.color = 'red';

//null 和 其它类型:其它类型的子类型
//1、
//var num2:number;
//console.log(num2)//输出:undefined 报错
//2、
//var num2:undefined;
//console.log(num2)//输出undefined 正确
//3、
var num3:number | undefined;
num3 = 123;
console.log(num3);
//4、定义了没有赋值就是undefined
var num4:number | undefined;
console.log(num4);
//5、
//var num5:null;
//num5 = 123;//报错
//6、一个元素可能是number类型，可能是null，可能是undefined
var num6:number | null | undefined;
num6 = 123;
console.log(num6);

//void类型
//es5的定义方法
function run1(){
    console.log('run1');
}
run1();
//方法没有返回任何类型
function run2():void {
    console.log('run2');
}
run2();
//错误写法
/*function run3():undefined {
    console.log('run3');
}
run3();*/
//正确写法
function run4():number {
    return 123;
}
run4();

//never
var aa:undefined;
aa = undefined;
var bb:null;
bb = null;

var cc:never;
//cc = 123;//错误的写法
cc = (() => {
   throw new Error('错误');
})()

//3.1.函数的定义
//es5定义函数的方法
//函数声明法
/*function run5() {
    return 'run5';
}
//匿名函数
var run6 = function () {
    return 'run6';
}*/
//ts中定义函数的方法
//函数声明法
function run7():string {
    return 'run7';
}
//匿名函数
var run8 = function():number {
    return 123;
}
run8();
//ts中定义方法传参
function getInfo1(name:string,age:number):string {
    return '${name}---${age}';
}
alert(getInfo1('jack',20));
var getInfo2 = function (name:string,age:number):string{
    return '${name}---${age}';
}
alert(getInfo2('marry',30));
//没有返回值的方法
function run9():void {
    console.log('run9')
}
run9();

//3.2.方法可选参数
//es5里面方法的实参和形参可以不一样，但是ts中必须一样，如果不一样就需要配置可选参数
function getInfo3(name:string,age?:number):string{
    if (age){
        return '${name}---${age}';
    }else {
        return '${name}---年龄保密';
    }
}
alert(getInfo3('jack'));
alert(getInfo3('jack',30));
//可选参数必须配置到参数的最后面

//3.3.默认参数
//es5里面没法设置默认参数，es6和ts中都可以设置默认参数
function getInfo4(name:string,age:number=20):string{
    if (age){
        return '${name}---${age}';
    }else {
        return '${name}---年龄保密';
    }
}
alert(getInfo4('jack'));
alert(getInfo4('jack',30));

//3.4.剩余参数
function sum1(a:number,b:number,c:number,d:number):number{
    return a+b+c+d;
}
alert(sum1(1,2,3,4));
//三点运算法，接收实参传递过来的值
//写法一
function sum2(...result:number[]):number{
    var sum = 0;

    for (let i = 0; i < result.length; i++) {
        sum += result[i];
    }
    return sum;
}
alert(sum2(1,2,3,4,5,6,7,8,9));
//写法二
function sum3(a:number,b:number,...result:number[]):number{
    var sum = a * 10 + b * 10;

    for (let i = 0; i < result.length; i++) {
        sum += result[i];
    }
    return sum;
}
alert(sum3(1,2,3,4,5,6,7,8,9));

//3.5.ts函数重载
//java中方法的重载:重载指的是两个或者两个以上的同名函数，但它们的参数不一样，这时会出现函数重载的情况。
//typescript中的重载:通过为同一个函数提供多个函数类型定义来实现多种功能的目的。
//ts为了兼容es5以及es6，重载写法和java中有区别。
//es5中出现同名的方法，下面的会替换上面的方法
/*
function css(config){

}
function css(config,value){

}*/
//ts中的重载
//1、
function getInfo5(name:string):string;
function getInfo5(age:number):number;
function getInfo5(str:any):any {
    if (typeof str === 'string'){
        return '我叫:' + str;
    }else {
        return '我的年龄是:' + str;
    }
}
alert(getInfo5('jack'))//正确
alert(getInfo5(123))//正确
//alert(getInfo5(true))//错误写法
//2、
function getInfo6(name:string):string;
function getInfo6(name:string,age:number):string;
function getInfo6(name:any,age?:any):any{
    if (age){
        return '我叫:' + name + '我的年龄是:' + age;
    }else {
        return '我叫:' + name;
    }
}
alert(getInfo6('jack',20));
alert(getInfo6('marry'));
//alert(getInfo6(30));//错误写法

//3.6.箭头函数  es6
//this指向的问题     箭头函数里面this指向上下文
setTimeout(function () {
    alert('run');
},1000)
setTimeout(() => {
    alert('run');
},1000)

